iT邦幫忙

2025 iThome 鐵人賽

DAY 13
0

很多學習 FP 的初學者,接觸 FP 不久,就產生了兩個很大的疑問:

  1. 我會用 map, filter, reduce 了,那我算是會 FP 了嗎?
  2. FP 的定義到底是什麼?

上述兩個問題,其實有點一體兩面,如果 FP 的定義就是 map, filter, reduce 的話,那就算是學會了。如果沒有這麼單純的話,那就…。

什麼是函數式編程 (FP)?定義為何?

很可惜,這個定義並沒有單純的答案。比起 Lisp 語言的定義,函數式編程的定義相對模糊多了。首先,稱之為函數式語言的程式語言,至少分為了兩大語言系統:

  1. Haskell 為代表的語言家族,特色是搭配了強靜態類型、類型推導、Monad 等。
  2. Clojure 為代表的語言家族,特色是動態型別,還有加上了 Lisp 。

所以,函數式編程的定義就會因人而異,見仁見智。有人會認為兩個語言系統取交集就算是。也有人會認為,沒有加上類型推導的話,就不算。

換言之,函數式編程的定義,就像是 Lisp 該不該積極使用 Macro 一樣,帶有爭議。

分離概念與實作

對於定義的議題,我認為,應該要把函數式編程 (FP) 看成兩個部分:概念與實作。

  • 概念:「計算」主要透過無副作用的資料轉換一再地疊加而達成。系統的狀態 (state) 因而可以最少化,因為計算的輸入與輸出都是不可變 (immutable) 的值 (value)。
  • 實作:這部分就形形色色,實作的部分是各式各樣子的可以用來輔助達成上述概念的機制 (mechanism),它們包含了:高階函數、函數做為第一類公民、Monad、Immutable Collection 等等的概念。

也基於這個分離概念與實作的觀點,我會主張:

  1. 函數式編程的重點在於「概念」。因為滿足了這個概念,計算的語意就會變得更高階,可以達成減少 bug 、還有可能更消耗系統資源的效果。
  2. 高階函數、函數做為第一類公民等這些機制,這些固然很像是許多函數式編程語言都共有的特性,但是,它們本質上也是實作。換言之,如果有某種語言,它可以達成函數式編程的概念,就算是沒有提供高階函數、函數做為第一類公民等特性,我還是會認為,它算是函數式編程。
  3. 更進一步來講:像 Linux Shell pipe 的某些寫法、 Modern Data Stack 裡的資料轉換、像 Datomic 這樣子的 Event sourcing 設計,我也都認為,它們都是函數式編程概念的體現。

小結

本篇探討了函數式編程(FP)的定義,指出 FP 的定義因不同的語言系統而存在爭議,但如果我們區分概念與實作之後,可以得到一個新的觀點。

FP 的核心概念在於使用無副作用的資料轉換來進行計算,盡量減少系統狀態,並使用不可變的值。而高階函數、Monad 等,都只是協助達成這個概念的實作機制。也因此,判斷是否屬於 FP,應著重於其是否體現了無副作用和不可變值的核心精神,而非拘泥於具體的實作工具。


上一篇
深入淺出函數式編程 (FP)—高階語意
下一篇
深入淺出函數式編程 (FP)—常見的機制
系列文
在 Neovim 中探索 Fennel 與函數式編程21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言